<?php defined('SYSPATH') or die('No direct script access.');

require Kohana::find_file('lib', 'swift_required');

class BBCode {
 
	public static function toXHTML($content) {
		$content = stripslashes($content);
		$content = str_replace(array("\r\n", "\r"), "\n", $content);
		$content = strip_tags($content);
		$content = self::longWords($content);
		$content = self::bold($content);
		$content = self::italic($content);
		$content = self::underline($content);
		$content = self::code($content);
		$content = self::unorderedList($content);
		$content = self::listItem($content);
		$content = self::colour($content);
		$content = self::size($content);
		$content = self::quote($content);
		$content = self::image($content);
		$content = self::url($content);
		$content = self::email($content);
		$content = self::emptyElements($content);
		$content = str_replace('&', '&amp;', $content);
		$content = nl2br(trim($content));
		$content = self::smilies($content);
		return $content;
	}
 
	private static function longWords($text) {
		$max_word_lenght	= 60;
		$max_link_lenght	= 200;
		$splitter				 = ' ';
		$lines = explode("\n", $text);
		foreach($lines as $key_line => $line) {
			$words = explode(' ', $line);
			foreach($words as $key_word => $word) {
				$word			 = preg_replace('/\[(.*)\]/Usi', '', trim($word));
				$max_lenght = (substr(strtolower($word), 0, 7) == 'http://' || substr(strtolower($word), 0, 8) == 'https://' || substr(strtolower($word), 0, 4) == 'www.') ? $max_link_lenght : $max_word_lenght;
				if (strlen($word) > $max_lenght) {
					$words[$key_word] = chunk_split($words[$key_word], $max_lenght, $splitter);
					$length					 = strlen($words[$key_word]) - strlen($splitter);
					$words[$key_word] = substr($words[$key_word], 0, $length);
				}
			}
			$lines[$key_line] = implode(' ', $words);
		}
		return implode("\n", $lines);
	}
 
	private static function bold($content) {
		return preg_replace('/\[b\](.*)\[\/b\]/Usi', '<strong>\\1</strong>', $content);
	}
 
	private static function italic($content) {
		return preg_replace('/\[i\](.*)\[\/i\]/Usi', '<em>\\1</em>', $content);
	}
 
	private static function underline($content) {
		return preg_replace('/\[u\](.*)\[\/u\]/Usi', '<span class="underline">\\1</span>', $content);
	}
 
	private static function code($content) {
		return preg_replace('/\[code\](.*)\[\/code\]/Usi', '<code>\\1</code>', $content);
	}
 
	private static function unorderedList($content) {
		$content = preg_replace('/\[list\](.*)\[\/list\]/Usi', '<ul>\\1</ul>', $content);
		return str_replace("<ul>\n", '<ul>', $content);
	}
 
	private static function listItem($content) {
		$content = preg_replace("/\[\*\](.*)\n/Usi", '<li>\\1</li>', $content);
		return str_replace("</li>\n", '</li>', $content);
	}
 
	private static function colour($content) {
		return preg_replace_callback('/\[color=(.*)\](.*)\[\/color\]/Usi', array('self', 'colourCallback'), $content);
	}
 
	private static function colourCallback($matches) {
		$colour	 = strtolower(str_replace('#', '', $matches[1]));
		$text		 = $matches[2];
		$colours	= array('aliceblue' => 'f0f8ff',
											'antiquewhite' => 'faebd7',
											// ...
											);
 
		if (array_key_exists($colour, $colours)) {
		 $class = $colour;
		}
		elseif (in_array($colour, $colours)) {
		 $class = array_search($colour, $colours);
		}
		else {
		 return $text;
		}
		return '<span class="'.$class.'">'.$text.'</span>';
	}
 
	private static function size($content) {
		return preg_replace_callback('/\[size=(.*)\](.*)\[\/size\]/Usi', array('self', 'sizeCallback'), $content);
	}
 
	private static function sizeCallback($matches) {
		$size	 = strtolower($matches[1]);
		$text	 = $matches[2];
		$sizes	= array('xs'	=> 7,
										's'	 => 9,
										'm'	 => 12,
										'l'	 => 18,
										'xl'	=> 24,
										// ...
										);
		if (array_key_exists($size, $sizes)) {
		 $class = $size;
		}
		elseif (in_array($size, $sizes)) {
		 $class = array_search($size, $sizes);
		}
		else {
		 return $text;
		}
		return '<span class="'.$class.'">'.$text.'</span>';
	}
 
	private static function quote($content) {
		while(preg_match('/\[quote\](.*)\[\/quote\]/Uis', $content)) {
			$content = preg_replace('/\[quote\](.*)\[\/quote\]/Uis', '<blockquote>\\1</blockquote>', $content);
		}
		while(preg_match('/\[quote="(.*)"\](.*)\[\/quote\]/Uis', $content)) {
			$content = preg_replace('/\[quote="(.*)"\](.*)\[\/quote\]/Uis', '<blockquote><p>\\1</p>\\2</blockquote>', $content);
		}
		return $content;
	}
 
	private static function image($content) {
		return preg_replace('/\[img\](.*)\[\/img\]/Usie', "'<img src=\"\\1\" alt=\"'.basename('\\1').'\" />'", $content);
	}
 
	private static function url($content) {
		$content = preg_replace_callback('/\[url\](.*)\[\/url\]/Usi', array('self', 'linkLenght'), $content);
		$content = preg_replace_callback('/\[url=(.*)\](.*)\[\/url\]/Usi', array('self', 'linkLenght'), $content);
		$content = preg_replace_callback('#(( |^)(((ftp|http|https|)://)|www\.)\S+)#mi', array('self', 'linkLenght'), $content);
		return $content;
	}
 
	private static function linkLenght($matches) {
		$url			= trim($matches[1]);
		$linktext = isset($matches[2]) && strlen($matches[2]) > 0 ? $matches[2] : $matches[1];
		if (strlen($linktext) > 50 && !substr_count(strtolower($linktext), '<img')) {
			$linktext = substr($linktext, 0, 45 - 3).' … '.substr($linktext, - 5);
		}
		$url = substr(strtolower($url), 0, 3) == 'www' ? 'http://'.$url : $url;
		return '<a href="'.$url.'" target="_blank">'.$linktext.'</a>';
	}
 
	private static function email($content) {
		$content = preg_replace('/\[email\](.*)\[\/email\]/Usi', '<a href="mailto:\\1">\\1</a>', $content);
		$content = preg_replace('/\[email=(.*)\](.*)\[\/email\]/Usi', '<a href="mailto:\\1">\\2</a>', $content);
		return $content;
	}
 
	private static function emptyElements($content) {
		return preg_replace('/<[a-z=\"\s]*>\s*<\/(.*)>/Usi', '', $content);
	}
	
	private static function smilies($content) {
		$smilies = explode('##########################################################################', file_get_contents(DOCROOT.'media/img/smilies/Set_Smiles_YarNET.pak'));
		$smilies = $smilies[2];
		$smilies = explode("\n", $smilies);
		$replace = array();
		$image = array();
		foreach ($smilies as $key => $smile) {
			$smilies[$key] = explode('=+:', $smile);
			if (count($smilies[$key]) == 3) {
				$replace[] = trim($smilies[$key][2]);
				$image[] = '<img src="/media/img/smilies/'.$smilies[$key][0].'" alt="'.htmlspecialchars(trim($smilies[$key][2])).'" />';
			}
		}
		$content = str_replace($replace, $image, $content);
		return $content;
	}
}